library ieee;
use ieee.std_logic_1164.all;
USE ieee.std_logic_arith.ALL;
use STD.textio.all;

entity multiplier_tb2 is
        
end entity multiplier_tb2;

architecture RTL of multiplier_tb2 is

    component multiplier is
        port (
                clk, reset, start, setMultiplicand, setMultiplier : in bit;
                dataInExternal : in bit_vector(31 downto 0);
                done : out bit;
                product : out bit_vector(63 downto 0)
        );
    end component;
        
        for all : multiplier use entity work.multiplier(Structural);
        
        signal clkIn, startIn, setMultiplicandIn, setMultiplierIn, endoffile, done: bit := '0';
        signal resetIn : bit := '1';
        signal doneOut : bit := '0';
        signal data, dataA, dataB : bit_vector(31 downto 0) := "00000000000000000000000000000000";
        signal productOut : bit_vector (63 downto 0) := "0000000000000000000000000000000000000000000000000000000000000000";
        signal check : std_logic_vector(63 downto 0);


begin

        clkIn <= not clkIn after 50 ns;
        
        MULTI : multiplier port map (clkIn, resetIn, startIn, setMultiplicandIn, setMultiplierIn, data, doneOut, productOut);
        
        tb : process
        
--Variables For Input
	file file_pointerIn : text;
    variable line_contentA, line_contentB: string(1 to 32);
    variable line_numIn: line;
    variable j : integer := 0;
    variable charA, charB: character :='0';
        
--Variables For Output

	file file_pointerOut : text;
    variable line_contentOut : string(1 to 64);
    variable bin_value : std_logic_vector(63 downto 0);
    variable line_numOut : line;
    variable i : integer := 0;
    variable charOut : character:='0';
        
   begin
        --Open the file read.txt from the specified location for reading(READ_MODE).
      file_open(file_pointerIn,"C:\Users\Scott\Documents\testInput.txt",READ_MODE);
      file_open(file_pointerOut,"C:\Users\Scott\Documents\testOutput.txt",WRITE_MODE);  
      while not endfile(file_pointerIn) loop --till the end of file is reached continue.


--Load DataA
      readline (file_pointerIn,line_numIn);  --Read the whole line from the file
        --Read the contents of the line from  the file into a variable.
      READ (line_numIn,line_contentA);
        --For each character in the line convert it to binary value.
        --And then store it in a signal named 'bin_value'.
        for j in 1 to 32 loop       
            charA := line_contentA(j);
            if(charA = '0') then
                dataA(32-j) <= '0';
            else
                dataA(32-j) <= '1';
            end if;
        end loop;        
        wait for 10 ns; --after reading each line wait for 10ns.


--Load DataB
      readline (file_pointerIn,line_numIn);  --Read the whole line from the file
        --Read the contents of the line from  the file into a variable.
      READ (line_numIn,line_contentB);
        --For each character in the line convert it to binary value.
        --And then store it in a signal named 'bin_value'.
        for j in 1 to 32 loop       
            charB := line_contentB(j);
            if(charB = '0') then
                dataB(32-j) <= '0';
            else
                dataB(32-j) <= '1';
            end if;
        end loop;   
        
        wait for 10 ns; --after reading each line wait for 10ns.
        
              
--start TestBench
			testBench: while doneOut = '0' loop
       	    wait for 105 ns;
        	    --change to Reset state
        	    resetIn <= '1';			
			
        	    wait for 105 ns;
        	    --change to input multiplier state
        	    startIn <= '1';
        	    resetIn <= '0';
        	    
        	    wait for 55 ns;
        	    --Load data into the Shift register
        	    data <= dataA;
        	    
        	    wait for 155 ns;
        	    --Move the Multiplicand to the lower 32 bits of the shift register
        	    startIn <= '0';
        	    setMultiplicandIn <= '1';
        	    
        	    wait for 155 ns;
        	    --change the data to be loaded in to the shift register
        	    data <= dataB;
        	    
        	    wait for 155 ns;
        	    setMultiplicandIn <= '0';
        	    wait for 30ns;
        	    --change the state to start the multiplication
        	    setMultiplierIn <= '1';
				wait for 105 ns;
				setMultiplierIn<='0';
				wait for 8 us;
				bin_value := To_StdLogicVector(productOut);
				check <= bin_value;
		end loop;
     	
     	wait for 105ns;	
     	resetIn <= '1';

     		
--Start Output of Product
     
        --convert each bit value to character for writing to file.
        for i in 0 to 63 loop
            if(check(i) = '0') then
                line_contentOut(64-i) := '0';
            else
                line_contentOut(64-i) := '1';
            end if;
        end loop;
        write(line_numOut,line_contentOut); --write the line.
        writeline (file_pointerOut,line_numOut); --write the contents into the file.
        wait for 500 ns;  --wait for 10ns after writing the current line.
	end loop;
	file_close(file_pointerIn);  --after reading all the lines close the file.
	file_close(file_pointerOut); --Close the file after writing. 
	wait;
	end process;
      
end architecture RTL;
